﻿using System;
using System.Collections.Generic;
using DNT.RavenQA.Core.Extensions;
using DNT.RavenQA.Core.KeyResolving;

namespace DNT.RavenQA.Core
{
    public class Entity<TKey> : IEquatable<Entity<TKey>>, IEntity
    {
        public virtual String Id { get; protected set; }

        public TKey Key
        {
            get { return (TKey)_resolvers[typeof(TKey)].Resolve(Id); }
        }

        public Boolean Equals(Entity<TKey> other)
        {
            if (ReferenceEquals(other, null))
                return false;

            var sameReference = ReferenceEquals(this, other);
            var sameValue = String.Equals(Id, other.Id, StringComparison.OrdinalIgnoreCase);

            return sameReference || sameValue;
        }

        public override Boolean Equals(Object obj)
        {
            var castedObj = obj as Entity<TKey>;
            return Equals(castedObj);
        }

        public override Int32 GetHashCode()
        {
            return Id.IsNotNull() ? Id.GetHashCode() : 0;
        }

        public static Boolean operator ==(Entity<TKey> left, Entity<TKey> right)
        {
            return Equals(left, right);
        }

        public static Boolean operator !=(Entity<TKey> left, Entity<TKey> right)
        {
            return !Equals(left, right);
        }

        private readonly IDictionary<Type, IKeyResolver> _resolvers = new Dictionary<Type, IKeyResolver>
                                                                          {
                                                                              {typeof(Int32), new Int32Resolver()}
                                                                          };

        internal Boolean HasSameId(String id)
        {
            id.EnsureIsNotNullOrEmpty("id");
            return String.Equals(id, Id, StringComparison.OrdinalIgnoreCase);
        }

        protected Boolean HasSameId(IEntity entity)
        {
            entity.EnsureIsNotNull("entity");
            return String.Equals(entity.Id, Id, StringComparison.OrdinalIgnoreCase);
        }
    }
}